#ifndef _protocol_dragonball_h
#define _protocol_dragonball_h

#include <functional>
#include <cstring>
#include <queue> 

#include "m01_spi.h"
#include "serial_manager.h"
#include "packet.h"

#include <sstream>
#define canbuslen 2
#define usartlen 8

#define inPinSw 8
#define inblen 1

#define gpin 2

#define batterylen 1

#define DeviceNumber 12
namespace igslib
{
	enum rawfield
	{
		Hfd=0,
		Lfd,
	    Cfd,
        Dfd	,	
	};
   
   enum usat
	{
		valid=0,
		busy,
		invalid,
	    error,	
	};
   
   struct box_t
    {      
		unsigned char startflg;
		unsigned char lastPN;
		unsigned char curPN;
		unsigned char count;
		bool transferflg;
		bool ISconnet;
		int connect_cnt;		
        box_t()
        {
            memset(this,0,sizeof(box_t));
			startflg=0x53;
			curPN = 0x81;
            lastPN = 2;
			transferflg=true;
			ISconnet=false;
        }
    };
	
	struct IKV_t
	{		
		 enum ikvlen
		{			                  
			macLen=10,                     
			chipidLen=10,     
			dataLen=16,
			respLen = 22, 
			challengeLen=22,			
			odcLen=78, 				
		};
		
	  struct auth_t
	  {
		  unsigned char RESP[respLen];
		  unsigned char MAC[macLen];  
	   }auth;				    
	  struct info_t
		{	  
		  unsigned short PID;
		  unsigned short VIP; 
		  unsigned char CHIPID[chipidLen];
		  unsigned char ODC[odcLen];
		  unsigned char Dlock;
		}info;	
	   struct ROMData_t
		{
		  unsigned char address;
		  unsigned char Data[dataLen];

		}ROMData;
	   bool IsBusy;   
	};
	
	struct DevReg_t
	{
		int nv;
		int st;
		DevReg_t()
		{
			nv = 0;
			st = 0;
		}
	};
	
	struct VRReg_t
	{
		int absnv;
		signed int relanv;
	};
	
	struct UsartReg_t
	{
		char nv[40];
		char len;
		char st;
		char SM;
	};
	
	struct CanReg_t
	{
		char nv[8];
		char valid;	
		 CanReg_t()
		 {
			for(int i=0;i<8;i++)
			nv[i]=0;
			valid=0;		
		 }	
	};
		
	class Protocol_DragonBall:public m01_spi
    {
        protected:	
		  char Rxbuff[256];
		  char Txbuff[256];
 		  std::queue<IPacket*> TxQueue;
		  std::function<void( std::vector<char>)> Device[DeviceNumber];
		  
		  box_t DelivBox;	    
		  IKV_t ikv_dev;
		    
		/******Board's devices allocate maximum account*********/
		  char input[gpin]; 
		  DevReg_t reg_coin[inPinSw];
		  char reg_meter[inblen];
		  DevReg_t reg_dispenser[inPinSw];
		  VRReg_t reg_vr[inPinSw/2];
		  UsartReg_t reg_usart[usartlen];
		  char reg_dipswitch[inblen];
		  std::map<int,CanReg_t*> reg_canbus[canbuslen] ;
		  char reg_battery[batterylen];
		  
       public:			
		 Protocol_DragonBall();
		 ~Protocol_DragonBall();
		virtual int Update();
		unsigned char u8checksum(char *ptr,int len);
		void PrepareIO(box_t* pptr, char *buf);
		void ProcessPn(box_t* io, char *buf);
		void short_to_bytes(unsigned short a0 ,unsigned char* a1);
		
		
		/******Device CMD list*********/
		
		void dev_gpio( std::vector<char> data);
		void dev_acceptor( std::vector<char> data);
		void dev_dispenser( std::vector<char> data);
		void dev_meter( std::vector<char> data);
		void dev_pwm( std::vector<char> data);
		void dev_vr( std::vector<char> data);
		void dev_canbus( std::vector<char> data);
		void dev_marquee( std::vector<char> data);
		void dev_usart( std::vector<char> data);
		void dev_IKV( std::vector<char> data);
		void dev_dipswitch( std::vector<char> data);
		void dev_battery( std::vector<char> data);
		
		/******IKV Function*********/
	    bool ikv_IsBusy();		
		int  ikv_GetInfo(unsigned char* bkval);	
		int  ikv_GetResponse(unsigned char* bkval);
		int  ikv_GetROMData(unsigned char* bkval);			
		void ikv_Setup();
		void ikv_SetROMData(int addr,char *data);	
		void ikv_SetROMaddr(int addr);
		void ikv_SetChallenge(unsigned char *data);			
		void ikv_DLock();
		
		/******GPIO Function*********/
		void SetGPout(char pin , char lv);
		int GetGPin(char *lv);
		
		
	   /******acceptor Function*********/
		int  GetAcceptorNV(char ID);
		int  GetAcceptorSat(char ID);
		void SetupAcceptor(char ID, char* AccData);
		/*!
         * @param func --ClrE --Inhibit
         * @return
         *     0: normal quit.
         *     -1: `func` mismatched.
         */
		int SetAcceptor(char ID, char data, const std::string& func);
																
		 /******dispenser Function*********/
		/*
         * @return
         *     >=0: normal value.
         *     -1: ID out of range.
         */
		int  GetDispenserNV(char ID);
		/*
         * @return
         *     >=0: normal value.
         *     -1: ID out of range.
         */
		int  GetDispenserSat(char ID);
		void SetupDispenser(char ID, char* DispData);
		/*
         * @return
         *     0: normal quit.
         *     -1: `func` mismatched.
         * @param a2 --Rest --PayOut
         */
		int SetDispenser(char ID, int data, const std::string& func);

		/******Meter Function*********/
		void SetupMeter(char ID, char* mtdata);
		void SetMeter(char ID, short val);
		char GetMeterNV(char ID);
		/******PWM Function*********/
		void SetupPWM(char ID, char* pwndata);
		void SetPWM(char ID, char val);

		/******VR Function*********/
        /*!
         * @param ID [in] 
         * @param result [out]
         * @return
         *     0: normal quit;
         *     -1: ID error;
         */
		int  GetVRabs(char ID,float* rtn);
        /*!
         * @param ID [in] 
         * @param result [out]
         * @return
         *     0: normal quit;
         *     -1: ID error;
         */
		int  GetVRrela(char ID,float* rtn);
		void SetupVR(char ID, char val);
		
	     /******CanBus Function*********/
		int  GetCanbusNV(char ID, char sID, char * candata);
		void SetCanbus(char ID, char tID,char* candata);
		void SetupCanbus(char ID, char* candata);
		void FlushCanbus(char ID,char sID);
		
		/******lamp Function*********/
		void LoadGroup(char ID,int len,char* marqdata);
        void LoadPattern(char ID,int len, char* marqdata);
		void SetMarquee(char ID, char* marqdata);
		void SetupMarquee(char ID, char* marqdata);			

		/******USART Function*********/
		int GetUsartNV(char ID,char * usdata);
		int GetUsartSat(char ID);
		void FlushUsart(char ID);
		void SetUsart(char ID,int len, char* usdata);
		void SetupUsart(char ID, char* usdata);	


		/******DipSwitch Function*********/
		char GetDipSwitchNV(char ID);
		void SetupDipSwitch(char ID, char dip);	


		/******Battery Function*********/
		char GetBatteryNV(char ID);
		void SetupBattery(char ID, char val);				

		
     };	  
};

#endif
